Linting tool是可以幫忙把關程式品質的工具,雖然它不是寫javascript必備的工作,但是當程式碼越來越複雜,或是團隊多人一起開發的時候,維持code的品質與coding style一致性就是很重要的事情!
它會用一套標準分析靜態的javascript code,當沒有達到標準規範,就會跳出訊息指示。它除了可以幫助建立coding style,還可以避免發生一些不預期的錯誤,像是結尾沒寫分號、使用沒有宣告導致變成全域變數...等問題,linting tool都能夠有效避免我們撰寫這些可能產生問題的程式碼,讓code看起來也更專業。
Javascript有許多這類工具可以使用,像是JSLint、JSHint、ESLint...等,但是ESLint是網路上大家都最推薦的一個,因為它非常有彈性,官方沒有認定哪一種style rules是最好的,所以任何rules都是pluggable,可以靠config設定你想要的規則,而且非常容易透過它的錯誤訊息找到問題,同時也支援ES6和JSX。
ESLint的特點在上面講的差不多XD,這邊只好再重述一下官網說的概念:
The pluggable linting utility for JavaScript and JSX
ESLint的幾項優點:
使用註解的方式,把config內容設定在單一檔案中,會面會講到這種方式,也可以叫inline comments。
可以設定在 .eslintrc 檔案或是package.json裡面的 eslintConfig 區段,和babel設定的方式很像,ESLint也會自動查找這個設定檔。而且 .eslintrc 支援在裡面的json寫註解。
.eslintrc的檔案,檔名可以是 .eslintrc ,也可以是 .eslintrc.* ,後面*代表不同語言格式,例如:.eslintrc.json。
查找的方式,假設資料夾結構如下:
project
├── .eslintrc
├── lib
│ └── source.js
└─┬ tests
├── .eslintrc
└── test.js
在lib資料夾裡面的檔案,會使用project/.eslintrc
的設定,而tests資料夾裡面的檔案,會使用project/.eslintrc
加上project/tests/.eslintrc
的設定,並且project/tests/.eslintrc
的設定優先。如果同一個資料夾下, .eslintrc 和package.json的eslintConfig 區段都有設定時,package.json內的不會被使用。
和git一樣的使用方式,ESLint也提供ignore讓我們設定哪些檔案可以被忽略。
設定環境,因為不同的環境中會有不同的global變數,例如:設定browser環境,這代表裡面會設定window..等,browser環境下特定的全域變數。可以到官網看有哪些環境可以設定,你也可以設定多個env,它們彼此之間是沒有衝突的。
{
"env": {
"browser": true,
"node": true
}
}
如果想使用的環境是來自於別的plugins,可以先指定沒有前綴詞 eslint-plugin- 的plugin名稱(example),加上一個斜線,後面接該plugin設定的環境名稱(custom):
{
"plugins": ["example"],
"env": {
"example/custom": true
}
}
如果只想針對單一檔案做這個設定,也可以在該檔案最上方加上:
/* eslint-env node, mocha */
設定自己定義的global變數,因為ESlint分析的是靜態的javascript,有一條規則:Disallow Undeclared Variables (no-undef),當js檔案中有使用到沒有定義的變數時它會報錯,不允許我們隨便使用global變數。但是某些時候,我們會使用一些第三方的library,例如:ga、mocha,在runtime時沒有問題,但在ESLint分析靜態檔案時會違反沒有定義的規則,所以使用到非環境本身的global變數,為了讓ESLint知道沒問題,就可以設定在globals這邊。
另外,也有一條規則是禁止改變全域變數:Disallow assignment to native objects or read-only global variables (no-global-assign),所以globals有額外的設定,讓這個變數是否可以重新指定、被更改。
這邊設定兩個global變數,var1設為true,表示可以重新指定,var2設為false,表示不允許重新指定(readonly):
{
"globals": {
"var1": true,
"var2": false
}
}
如果只想針對單一檔案做這個設定,也可以在該檔案最上方加上:
/* global var1, var2 */
// 或是
/* global var1:false, var2:false */
前面其實有稍微提到,如果要使用第三方定義好的plugins就可以透過這邊設定,第三方plugins名稱通常長這樣 eslint-plugin-* ,當然也要先npm install要使用的packages,然後設定plugins時,這些packages的前綴詞 eslint-plugin- 可以保留或去掉只留後面名稱。
{
"plugins": [
"plugin1",
"eslint-plugin-plugin2"
]
}
這邊是真正制定規則的地方,可以設定每一條規則是否啟用,或是有額外調整的選項。ESLint提供了非常多,真的非常多的rules可以設定,除了可以用 .eslintrc 設定,也可以像前面提到的在單一檔案做設定。
規則的錯誤級別,有三個值可以設定:
以下rules設定的範例:
{
"rules": {
"eqeqeq": "off",
"curly": "error",
"quotes": ["error", "double"]
}
}
如果只想針對單一檔案做這個設定,也可以在該檔案最上方加上:
/* eslint curly: 2, quotes: ["error", "double"] */
// 或是
/* eslint eqeqeq: "off", curly: "error" */
如果使用第三方plugins,又希望改變其中一條rule,就可以用"plugin名稱/規則名稱"當key。像我們寫React通常會使用到的是eslint-plugin-react這個plugins,這邊用它來當範例,可以參考下面 react/jsx-indent 設定方式:
{
"plugins": [
"react"
],
"rules": {
"eqeqeq": "off",
"curly": "error",
"quotes": ["error", "double"],
"react/jsx-indent": ["error", 4]
}
}
繼承第三方config的設定,我們可以設定多組extends,也可以使用rule覆蓋它原本的規則,或是加上新的rule。Extends單一的config,在設定extends時,前綴詞 eslint-config- 也可以保留或去掉只留後面名稱。
{
"extends": "extend1",
"rules": {
"eqeqeq": "off",
"curly": "error",
"quotes": ["error", "double"]
}
}
有時候希望可以在只有單一檔案或是局部程式碼設定不同rule,可以透過inline註解的方式設定。
/* eslint-disable no-alert */
alert('foo');
/* eslint-disable */
alert('foo');
/* eslint-enable */
/* eslint-disable no-alert, no-console */
alert('foo');
console.log('bar');
/* eslint-enable no-alert, no-console */
alert('foo'); // eslint-disable-line
// eslint-disable-next-line
alert('foo');
alert('foo'); // eslint-disable-line no-alert
// eslint-disable-next-line no-alert
alert('foo');
現在,我們對ESLint config設定應該很有概念了!下一篇會來介紹extends的方式,並且實際修正我們todos的範例。
A Comparison of JavaScript Linting Tools
ESLint User Guide
想問一下邦友:環境變數的功能.
我若有個規則: no-var:error
則加上環境變數browser
這樣組合起來是什麼意思??